using System;
using System.Reflection;

using Tao.Lua;
using log4net;

namespace Playtime.RegionModule
{
	/// <summary>
	/// This class describes a concrete value of a string attribute, one instance per object
	/// having this attribute
	/// </summary>
	public class StringAttributeInstance : ClassState<StringAttributeInstance>, IAttributeInstance
	{
		/// <summary>
		/// Attribute describing this instance
		/// </summary>
		Attribute mAttribute;
		
		/// <summary>
		/// This defines the Lua class name (not object name) of the attribute
		/// </summary>
		private static string LuaClassName = "StringAttributeValue";
		public override string ClassName { get { return LuaClassName; } }
		
		/// <summary>
		/// The actual value contained in this instances
		/// </summary>
		public string Value = "Value of Str";
		
		public LuaApi Api { get { return LuaApi.Singleton;} } 
		
		public StringAttributeInstance(Attribute a) : base()
		{
			mAttribute = a;
		}
		
		public void RegisterApi(IntPtr luaState)
		{
			Api.Register(luaState);
		}

		/// <summary>
		/// Define the object as a field on a table with a specific name
		/// </summary>
		/// <param name="luaState">
		/// A <see cref="IntPtr"/>The lua state containing the table
		/// </param>
		/// <param name="name">
		/// The <see cref="System.String"/> name the object will have
		/// </param>
		public void DefineObjectAsField(IntPtr luaState, string name)
		{
			Lua.lua_pushstring(luaState, "_G");				// _G[<AttributeName>] = m
			Lua.lua_rawget(luaState, 1);
			int _G = Lua.lua_gettop(luaState);
			Lua.lua_pushstring(luaState, name);		
			PushOntoLuaStack(luaState, this, ClassName);
			Lua.lua_rawset(luaState, _G);
    	}

		/// <summary>
		/// Define the object as a field on a table with the default name for this attribute
		/// </summary>
		/// <param name="luaState">
		/// A <see cref="IntPtr"/> reference to the lua state where the name should be defined
		/// </param>
		public void DefineObjectAsField(IntPtr luaState)
		{
			DefineObjectAsField(luaState, mAttribute.DefaultObjectName);
		}
		
		#region Methods callable from lua
		public class LuaApi : LuaClass<StringAttributeInstance>
		{
			private static LuaApi mSingleton;
		
			public static LuaApi Singleton
			{
				get
				{
					if(mSingleton == null)
						mSingleton = new LuaApi();
					return mSingleton;
				}
			}

			private LuaApi()
			{
				ModuleName = StringAttributeInstance.LuaClassName;

				AddMethod("getvalue", GetValue);
				AddMethod("setvalue", SetValue);
			}

			int GetValue(IntPtr luaState)
			{
				StringAttributeInstance a = LoadSelfFromLuaStack(luaState, ModuleName);
				Lua.lua_pushstring(luaState, a.Value);
				return 1;
			}

			int SetValue(IntPtr luaState)
			{
				int argc = Lua.lua_gettop(luaState);
				if(argc == 2)
				{
					StringAttributeInstance a = LoadSelfFromLuaStack(luaState, ModuleName);
					a.Value = Lua.lua_tostring(luaState, 2);
				}
				else
				{
					Lua.lua_pushstring(luaState, "Invalid number of parameters passed to 'setvalue'");
					Lua.lua_error(luaState);
				}
				return 0;
			}
		}
		#endregion
	}
}

